<?php
namespace core\models;
/**
 * Session类
 * @package core\models
 * @author  ZhouHaoHua <53027327@qq.com>
 */
class Sessions {
    /**
     * @var \core\models\Sessions_Memcache
     */
    private static $_se = array();

    /**
     * 初始化Session
     * @param string $type          Session处理类型，支持mysql、system和memcache这几种方式
     * @param string $sessionName   会话名称
     * @param int    $lifeLength    会话生命周期(秒)
     * @param string $cookie_path   此 cookie 的有效 路径。 on the domain where 设置为“/”表示对于本域上所有的路径此 cookie 都可用。
     * @param string $cookie_domain Cookie 的作用 域。 例如：“www.php.net”。 如果要让 cookie 在所有的子域中都可用，此参数必须以点（.）开头，例如：“.php.net”。
     * @param string $save_dir session文件的保存位置，在以system方式保存时有效。例如：“/tmp”。
     * @return \core\models\Sessions_Memcache
     */
    public static function Open($type = 'system', $sessionName = 'zOsCid', $lifeLength = 1440, $cookie_path = '/', $cookie_domain = '.zframework.com', $save_dir = Z_SESSION_DIR) {
        $type = ucfirst($type);
        $tag = $type . $sessionName . $lifeLength;
        if (empty(self::$_se[$tag])) {
            $class           = 'core\models\Sessions_' . $type;
            $handle          = new $class($sessionName, $lifeLength);
            self::$_se[$tag] = $handle;

            // 设置session名和ID值
            session_name($sessionName);
            $sn = session_name();
            // 设置用户在关闭cookie的情况下也可以取session的功能
            if (isset($_POST[$sn])) {
                session_id($_POST[$sn]);
            } elseif (isset($_GET[$sn])) {//$_SERVER['SERVER_PORT']=='443' &&
                session_id($_GET[$sn]);
            }

            if ($type == 'System' && $save_dir ) {
                //session文件保存路径
                $path = $save_dir;
                //echo $path;exit;
                @mkdir($path, 0777, true);
                ini_set('session.save_path', $path);
            }

            self::cookieSet($sn, $lifeLength, $cookie_path, $cookie_domain);

            session_start();

        }
        return self::$_se[$tag];
    }

    /**
     * session的cookie失效机制设置
     * @param $sessionName
     * @param $lifeLength
     * @param $cookie_path
     * @param $cookie_domain
     */
    private static function cookieSet($sessionName, $lifeLength, $cookie_path, $cookie_domain){
        //echo $sessionName.'|'.$lifeLength.'|'.$cookie_path.'|'.$cookie_domain; exit;
        session_set_cookie_params($lifeLength, $cookie_path, $cookie_domain);
        ini_set('session.use_only_cookies', 1);
        if (isset($_COOKIE[$sessionName])) {
            $t = time();
            // 设置浏览器关闭时session必须失效
            setcookie($sessionName, $_COOKIE[$sessionName], 0, $cookie_path, $cookie_domain);
            if(!isset($_COOKIE[$sessionName.'time'])) {
                $_COOKIE[$sessionName.'time'] = $t;
                setcookie($sessionName.'time', $_COOKIE[$sessionName.'time'], 0, $cookie_path, $cookie_domain);
            }
            if($_COOKIE[$sessionName.'time'] + $lifeLength < $t){
                setcookie($sessionName, $_COOKIE[$sessionName], ($t - 1), $cookie_path, $cookie_domain);
                unset($_COOKIE[$sessionName]);
            }
            $_COOKIE[$sessionName.'time'] = $t;
            setcookie($sessionName.'time', $_COOKIE[$sessionName.'time'], 0, $cookie_path, $cookie_domain);
        }
    }
    /**
     * SESSION工厂类
     * @throws \ErrorException 提示团员成员此类不能直接new
     */
    private function __construct() {
        throw \Z::Error('此类不能直接new');
    }
}